package live.sidian.database.synchronizer;

import live.sidian.database.synchronizer.infrastructure.utils.Assert;
import live.sidian.database.synchronizer.infrastructure.utils.CollUtil;
import live.sidian.database.synchronizer.sync.data.DataSyncer;
import live.sidian.database.synchronizer.sync.structure.DiffExecutor;
import live.sidian.database.synchronizer.sync.structure.MetaData;
import live.sidian.database.synchronizer.sync.structure.MetaDataBuilder;
import live.sidian.database.synchronizer.sync.structure.MetaDataComparator;
import live.sidian.database.synchronizer.sync.structure.MetaDataComparator.Diff;
import live.sidian.database.synchronizer.sync.structure.model.Database;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author sidian
 * @date 2020/3/21 15:22
 */
@Slf4j
@Service
public class Synchronizer {

    /**
     * 同步结构
     */
    public void syncStructure(Database source, Database target) {
        // 参数校验
        Assert.isTrue(source.isReady(), "source参数不完整", IllegalArgumentException.class);
        Assert.isTrue(target.isReady(), "target参数不完整", IllegalArgumentException.class);
        // 数据库元数据初始化
        MetaData sourceMetaData = MetaDataBuilder.build(source);
        MetaData targetMetaData = MetaDataBuilder.build(target);
        // 比较
        Diff diff = MetaDataComparator.diff(sourceMetaData, targetMetaData);
        // 打印
        log.info("补丁打印");
        System.out.println(diff.toString());
        // 执行
        log.info("执行补丁");
        new DiffExecutor(target.toSqlHelper(true)).execute(diff);
    }

    /**
     * 同步数据. 使用前, 确保表结构一致
     *
     * @param source 源数据库
     * @param target 目标数据库
     * @param tables 要同步的表, 若为空或null, 则同步源数据库的所有表.
     */
    public void syncData(Database source, Database target, @Nullable List<String> tables) {
        // 参数校验
        Assert.isTrue(source.isReady(), "source参数不完整", IllegalArgumentException.class);
        Assert.isTrue(target.isReady(), "target参数不完整", IllegalArgumentException.class);
        // 同步
        DataSyncer syncer = new DataSyncer(source, target);
        if (CollUtil.isEmpty(tables)) {
            syncer.sync();
        } else {
            syncer.sync(tables);
        }
    }

}
